package com.sc.nft.admin.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.sc.nft.admin.request.*;
import com.sc.nft.annotation.SysMemberLogin;
import com.sc.nft.dao.DigitalCollectionDao;
import com.sc.nft.dao.EquityPropsDao;
import com.sc.nft.dao.EquitySharePanelDao;
import com.sc.nft.entity.DigitalCollection;
import com.sc.nft.entity.EquityProps;
import com.sc.nft.entity.SecondEquityPropsConfig;
import com.sc.nft.entity.vo.AdminSecondEquityPropsOrderListVO;
import com.sc.nft.entity.vo.AdminSecondEquityPropsPageVO;
import com.sc.nft.entity.vo.SecondConSignEquityPropsVO;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.AdminSecondEquityPropsService;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.Objects;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/second/equity/props")
@Api(tags = "二级市场管理")
public class AdminSecondEquityPropsController {

    private final EquityPropsDao equityPropsDao;
    private final AdminSecondEquityPropsService adminSecondEquityPropsService;
    private final EquitySharePanelDao equitySharePanelDao;
    private final DigitalCollectionDao digitalCollectionDao;


    @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "新增寄售权益道具配置", notes = "新增寄售权益道具配置", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result addSecondEquityPropsConf(@Valid @RequestBody AddSecondEquityPropsRequest request) {
        EquityProps equityProps = equityPropsDao.getById(request.getEquityPropsId());
        Assert.notNull(equityProps, () -> new GlobalRunTimeException("权益道具未找到"));
        if (request.getPanelId() != null) {
            Assert.notNull(equitySharePanelDao.getById(request.getPanelId()), () -> new GlobalRunTimeException("分红模板未找到"));
        }
        //校验是否开启求购
        checkAddWantBuy(request);
        SecondEquityPropsConfig secondEquityPropsConfig = BeanUtil.copyProperties(request, SecondEquityPropsConfig.class);
        adminSecondEquityPropsService.addSecondEquityPropsConf(equityProps.getId(), secondEquityPropsConfig);
        return Result.success();
    }


    @PostMapping(value = "/page", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "寄售列表", notes = "寄售列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<AdminSecondEquityPropsPageVO> page(@Valid @RequestBody SecondEquityPropsRequest request) {
        return PageResult.success(adminSecondEquityPropsService.getPage(request.getFirstTitle(), request.toMp()));
    }

    @PostMapping(value = "/edit", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "編輯二级市场藏品(新增寄售藏品)", notes = "編輯二级市场藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result editSecondCollection(@Valid @RequestBody EditSecondEquityPropsRequest request) {
        if (request.getPanelId() != null) {
            Assert.notNull(equitySharePanelDao.getById(request.getPanelId()), () -> new GlobalRunTimeException("分红模板未找到"));
        }
        SecondEquityPropsConfig oldSecondEquityPropsConfig = adminSecondEquityPropsService.getSecondEquityPropsConf(request.getId());
        Assert.notNull(oldSecondEquityPropsConfig, () -> new GlobalRunTimeException("集售不存在"));
        //校验是否开启求购
        checkEditWantBuy(request, oldSecondEquityPropsConfig.getEquityPropsId());
        SecondEquityPropsConfig secondEquityPropsConfig = BeanUtil.copyProperties(request, SecondEquityPropsConfig.class);
        adminSecondEquityPropsService.editSecondCollection(secondEquityPropsConfig);
        return Result.success();
    }


    @PostMapping(value = "/updateStatusById", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "上下架", notes = "上下架", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result enable(@Valid @RequestBody StatusRequest request) {
        adminSecondEquityPropsService.updateStatusById(request.getId(), request.getStatus());
        return Result.success();
    }

    @PostMapping(value = "/updateSortById", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "修改排序", notes = "修改排序", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result updateSortById(@Valid @RequestBody SortRequest request) {
        adminSecondEquityPropsService.updateSortById(request.getId(), request.getSort());
        return Result.success();
    }


    @PostMapping(value = "/conSignEquityPropsPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "寄售权益道具列表(寄售列表)", notes = "交易权益道具列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<SecondConSignEquityPropsVO> adminConSignPage(@Valid @RequestBody AdminSecondConSignEquityPropsRequest request) {
        return PageResult.success(adminSecondEquityPropsService.adminConSignPage(request.getUserTel(), request.getStartTime(), request.getStatus(), request.getEndTime(), request.toMp()));
    }

    @PostMapping(value = "/dealEquityPropsPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "交易列表(权益道具)", notes = "交易列表(权益道具)", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<AdminSecondEquityPropsOrderListVO> adminDealEquityPropsPage(@Valid @RequestBody AdminSecondEquityPropsOrderListRequest request) {
        return PageResult.success(adminSecondEquityPropsService.adminDealEquityPropsPage(request.getBuyUserTel(), request.getSalesUserTel(), request.getFirstTitle(), request.getStartTime(), request.getEndTime(), request.getDealStartTime(), request.getDealEndTime(), request.toMp()));
    }

    /**
     * 校验是否开启求购
     *
     * @param request
     */
    private void checkAddWantBuy(AddSecondEquityPropsRequest request) {
        if (request.getEnableWantBuy()) {
            Assert.notNull(request.getMinPrice(), () -> new GlobalRunTimeException("最低求购价格不能为空"));
            Assert.notNull(request.getMaxPrice(), () -> new GlobalRunTimeException("最高求购价格不能为空"));
            Assert.isTrue(request.getMinWantBuyPrice().compareTo(request.getMaxWantBuyPrice()) <= 0, () -> new GlobalRunTimeException("最高求购价格不能低于最低求购价格"));
            Assert.notNull(request.getWantBuyQuantity(), () -> new GlobalRunTimeException("单次最高求购价格不能为空"));
            Assert.isTrue(request.getWantBuyQuantity() > 0, () -> new GlobalRunTimeException("单次最高求购价格必须大于0"));
            Assert.notNull(request.getEnableWantBuyHoldCondition(), () -> new GlobalRunTimeException("求购持有条件不能为空"));
            Assert.notNull(request.getEnableWantBuyConsumeProp(), () -> new GlobalRunTimeException("求购消耗道具不能为空"));
            if (request.getEnableWantBuyHoldCondition()) {
                Assert.notNull(request.getWantBuyHoldCollectionId(), () -> new GlobalRunTimeException("持有藏品不能为空"));
                DigitalCollection digitalCollection = digitalCollectionDao.getById(request.getWantBuyHoldCollectionId());
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("持有藏品不存在"));
            } else {
                request.setWantBuyHoldCollectionId(null);
            }
            if (request.getEnableWantBuyConsumeProp()) {
                Assert.notNull(request.getWantBuyConsumePropId(), () -> new GlobalRunTimeException("消耗道具不能为空"));
                Assert.notNull(request.getWantBuyConsumePropQuantity(), () -> new GlobalRunTimeException("消耗道具数量不能为空"));
                Assert.isTrue(request.getWantBuyConsumePropQuantity() > 0, () -> new GlobalRunTimeException("消耗道具数量必须大于0"));
                Assert.isFalse(Objects.equals(request.getEquityPropsId(), request.getWantBuyConsumePropId()), () -> new GlobalRunTimeException("消耗道具不能与集售道具一致"));
                EquityProps equityProps = equityPropsDao.getById(request.getWantBuyConsumePropId());
                Assert.notNull(equityProps, () -> new GlobalRunTimeException("消耗道具不存在"));
                Assert.isTrue(equityProps.getStatus(), () -> new GlobalRunTimeException("消耗道具已下架"));
            } else {
                request.setWantBuyConsumePropId(null);
                request.setWantBuyConsumePropQuantity(null);
            }
        } else {
            request.setMinWantBuyPrice(null);
            request.setMaxWantBuyPrice(null);
            request.setWantBuyQuantity(null);
            request.setEnableWantBuyHoldCondition(null);
            request.setEnableWantBuyConsumeProp(null);
            request.setWantBuyHoldCollectionId(null);
            request.setWantBuyConsumePropId(null);
            request.setWantBuyConsumePropQuantity(null);
        }
    }

    /**
     * 校验是否开启求购
     *
     * @param request
     */
    private void checkEditWantBuy(EditSecondEquityPropsRequest request, Long equityPropsId) {
        if (request.getEnableWantBuy()) {
            Assert.notNull(request.getMinPrice(), () -> new GlobalRunTimeException("最低求购价格不能为空"));
            Assert.notNull(request.getMaxPrice(), () -> new GlobalRunTimeException("最高求购价格不能为空"));
            Assert.isTrue(request.getMinWantBuyPrice().compareTo(request.getMaxWantBuyPrice()) <= 0, () -> new GlobalRunTimeException("最高求购价格不能低于最低求购价格"));
            Assert.notNull(request.getWantBuyQuantity(), () -> new GlobalRunTimeException("单次最高求购价格不能为空"));
            Assert.isTrue(request.getWantBuyQuantity() > 0, () -> new GlobalRunTimeException("单次最高求购价格必须大于0"));
            Assert.notNull(request.getEnableWantBuyHoldCondition(), () -> new GlobalRunTimeException("求购持有条件不能为空"));
            Assert.notNull(request.getEnableWantBuyConsumeProp(), () -> new GlobalRunTimeException("求购消耗道具不能为空"));
            if (request.getEnableWantBuyHoldCondition()) {
                Assert.notNull(request.getWantBuyHoldCollectionId(), () -> new GlobalRunTimeException("持有藏品不能为空"));
                DigitalCollection digitalCollection = digitalCollectionDao.getById(request.getWantBuyHoldCollectionId());
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("持有藏品不存在"));
            } else {
                request.setWantBuyHoldCollectionId(null);
            }
            if (request.getEnableWantBuyConsumeProp()) {
                Assert.notNull(request.getWantBuyConsumePropId(), () -> new GlobalRunTimeException("消耗道具不能为空"));
                Assert.notNull(request.getWantBuyConsumePropQuantity(), () -> new GlobalRunTimeException("消耗道具数量不能为空"));
                Assert.isTrue(request.getWantBuyConsumePropQuantity() > 0, () -> new GlobalRunTimeException("消耗道具数量必须大于0"));
                Assert.isFalse(Objects.equals(equityPropsId, request.getWantBuyConsumePropId()), () -> new GlobalRunTimeException("消耗道具不能与集售道具一致"));
                EquityProps equityProps = equityPropsDao.getById(request.getWantBuyConsumePropId());
                Assert.notNull(equityProps, () -> new GlobalRunTimeException("消耗道具不存在"));
                Assert.isTrue(equityProps.getStatus(), () -> new GlobalRunTimeException("消耗道具已下架"));
            } else {
                request.setWantBuyConsumePropId(null);
                request.setWantBuyConsumePropQuantity(null);
            }
        } else {
            request.setMinWantBuyPrice(null);
            request.setMaxWantBuyPrice(null);
            request.setWantBuyQuantity(null);
            request.setEnableWantBuyHoldCondition(null);
            request.setEnableWantBuyConsumeProp(null);
            request.setWantBuyHoldCollectionId(null);
            request.setWantBuyConsumePropId(null);
            request.setWantBuyConsumePropQuantity(null);
        }
    }

}
